home *** CD-ROM | disk | FTP | other *** search
- //-----------------------------------------------------------------------------
- // File: useful.cpp
- //
- // Desc: Contains various utility classes and functions to help the
- // UI carry its operations more easily.
- //
- // Copyright (C) 1999-2001 Microsoft Corporation. All Rights Reserved.
- //-----------------------------------------------------------------------------
-
- #include <windows.h>
- #include <tchar.h>
- #include <wchar.h>
- #include <stdio.h>
- #include <stdarg.h>
-
- // assert include (make sure assert actually works with build)
- #ifdef DBG
- #undef NDEBUG
- #endif
- #include <assert.h>
-
- #include "useful.h"
- #include "collections.h"
-
-
- /*--------- \/ stuff for collections.h \/ ---------*/
- BOOL AfxIsValidAddress( const void* lp, UINT nBytes, BOOL bReadWrite)
- {
- // return lp != NULL;
-
- // simple version using Win-32 APIs for pointer validation.
- return (lp != NULL && !IsBadReadPtr(lp, nBytes) &&
- (!bReadWrite || !IsBadWritePtr((LPVOID)lp, nBytes)));
- }
-
- CPlex* PASCAL CPlex::Create(CPlex*& pHead, UINT nMax, UINT cbElement)
- {
- assert(nMax > 0 && cbElement > 0);
- CPlex* p = (CPlex*) new BYTE[sizeof(CPlex) + nMax * cbElement];
- // may throw exception
- if (p)
- {
- p->pNext = pHead;
- pHead = p; // change head (adds in reverse order for simplicity)
- }
- return p;
- }
-
- void CPlex::FreeDataChain() // free this one and links
- {
- CPlex* p = this;
- while (p != NULL)
- {
- BYTE* bytes = (BYTE*) p;
- CPlex* pNext = p->pNext;
- delete[] bytes;
- p = pNext;
- }
- }
- /*--------- /\ stuff for collections.h /\ ---------*/
-
-
- int ConvertVal(int x, int a1, int a2, int b1, int b2)
- {
- assert(a1 != a2 && a2 - a1);
- return MulDiv(x - a1, b2 - b1, a2 - a1) + b1;
- }
-
- double dConvertVal(double x, double a1, double a2, double b1, double b2)
- {
- assert(a1 != a2 && a2 - a1);
- return (x - a1) * (b2 - b1) / (a2 - a1) + b1;
- }
-
- SIZE GetRectSize(const RECT &rect)
- {
- SIZE size = {
- rect.right - rect.left,
- rect.bottom - rect.top};
- return size;
- }
-
- SIZE GetTextSize(LPCTSTR tszText, HFONT hFont)
- {
- if (!tszText)
- {
- SIZE z = {0, 0};
- return z;
- }
- RECT trect = {0, 0, 1, 1};
- HDC hDC = CreateCompatibleDC(NULL);
- if (hDC != NULL)
- {
- HGDIOBJ hOld = NULL;
- if (hFont)
- hOld = SelectObject(hDC, hFont);
- DrawText(hDC, tszText, -1, &trect, DT_CALCRECT | DT_NOPREFIX);
- if (hFont)
- SelectObject(hDC, hOld);
- DeleteDC(hDC);
- }
- SIZE size = {trect.right - trect.left, trect.bottom - trect.top};
- return size;
- }
-
- int GetTextHeight(HFONT hFont)
- {
- static const TCHAR str[] = _T("Happy Test! :D");
- SIZE size = GetTextSize(str, hFont);
- return size.cy;
- }
-
- int vFormattedMsgBox(HINSTANCE hInstance, HWND hParent, UINT uType, UINT uTitle, UINT uMsg, va_list args)
- {
- int i;
- const int len = 1024;
- static TCHAR title[len], format[len], msg[len];
-
- if (!LoadString(hInstance, uTitle, title, len))
- _tcscpy(title, _T("(could not load title string)"));
-
- if (!LoadString(hInstance, uMsg, format, len))
- return MessageBox(hParent, _T("(could not load message/format string)"), title, uType);
-
- #ifdef WIN95
- {
- char *psz = NULL;
- char szDfs[1024]={0};
- strcpy(szDfs,format); // make a local copy of format string
- while (psz = strstr(szDfs,"%p")) // find each %p
- *(psz+1) = 'x'; // replace each %p with %x
- i = _vsntprintf(msg, len, szDfs, args); // use the local format string
- }
- #else
- {
- i = _vsntprintf(msg, len, format, args);
- }
- #endif
-
- if (i < 0)
- return MessageBox(hParent, _T("(could not format message)"), title, uType);
-
- if (i < 1)
- msg[0] = 0;
-
- return MessageBox(hParent, msg, title, uType);
- }
-
- int FormattedMsgBox(HINSTANCE hInstance, HWND hParent, UINT uType, UINT uTitle, UINT uMsg, ...)
- {
- va_list args;
- va_start(args, uMsg);
- int i = vFormattedMsgBox(hInstance, hParent, uType, uTitle, uMsg, args);
- va_end(args);
- return i;
- }
-
- BOOL UserConfirm(HINSTANCE hInstance, HWND hParent, UINT uTitle, UINT uMsg, ...)
- {
- va_list args;
- va_start(args, uMsg);
- int i = vFormattedMsgBox(hInstance, hParent, MB_ICONQUESTION | MB_YESNO, uTitle, uMsg, args);
- va_end(args);
- return i == IDYES;
- }
-
- int FormattedErrorBox(HINSTANCE hInstance, HWND hParent, UINT uTitle, UINT uMsg, ...)
- {
- va_list args;
- va_start(args, uMsg);
- int i = vFormattedMsgBox(hInstance, hParent, MB_OK | MB_ICONSTOP, uTitle, uMsg, args);
- va_end(args);
- return i;
- }
-
- int FormattedLastErrorBox(HINSTANCE hInstance, HWND hParent, UINT uTitle, UINT uMsg, DWORD dwError)
- {
- // format an error message from GetLastError().
- LPVOID lpMsgBuf = NULL;
- DWORD result = FormatMessage(
- FORMAT_MESSAGE_ALLOCATE_BUFFER |
- FORMAT_MESSAGE_FROM_SYSTEM |
- FORMAT_MESSAGE_IGNORE_INSERTS,
- NULL,
- dwError,
- MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
- (LPTSTR) &lpMsgBuf,
- 0,
- NULL);
-
- if (!result || lpMsgBuf == NULL)
- return FormattedErrorBox(hInstance, hParent, uTitle, uMsg,
- _T("An unknown error occured (could not format the error code)."));
-
- int i = FormattedErrorBox(hInstance, hParent, uTitle, uMsg, (LPCTSTR)lpMsgBuf);
-
- LocalFree(lpMsgBuf);
-
- return i;
- }
-
- LPTSTR AllocLPTSTR(LPCWSTR wstr)
- {
- if (wstr == NULL)
- return NULL;
-
- #ifdef UNICODE
- return _tcsdup(wstr);
- #else
- int len = wcslen(wstr) * 2 + 1;
- char *ret = (char *)malloc(len);
- if (!ret)
- return NULL;
- WideCharToMultiByte(CP_ACP, 0, wstr, -1, ret, len, NULL, NULL);
- ret[len-1] = '\0';
- return ret;
- #endif
- }
-
- LPTSTR AllocLPTSTR(LPCSTR str)
- {
- if (str == NULL)
- return NULL;
-
- #ifndef UNICODE
- return _tcsdup(str);
- #else
- int len = strlen(str);
- WCHAR *ret = (WCHAR *)malloc((len + 1) * sizeof(WCHAR));
- if (!ret)
- return NULL;
- mbstowcs(ret, str, len);
- ret[len] = L'\0';
- return ret;
- #endif
- }
-
- void CopyStr(LPWSTR dest, LPCWSTR src, size_t max)
- {
- if (dest == NULL || src == NULL)
- return;
-
- wcsncpy(dest, src, max);
- }
-
- void CopyStr(LPSTR dest, LPCSTR src, size_t max)
- {
- if (dest == NULL || src == NULL)
- return;
-
- strncpy(dest, src, max);
- }
-
- void CopyStr(LPWSTR dest, LPCSTR src, size_t max)
- {
- if (dest == NULL || src == NULL)
- return;
-
- mbstowcs(dest, src, max);
- }
-
- void CopyStr(LPSTR dest, LPCWSTR src, size_t max)
- {
- if (dest == NULL || src == NULL)
- return;
-
- WideCharToMultiByte(CP_ACP, 0, src, -1, dest, max, NULL, NULL);
- }
-
- LPWSTR AllocLPWSTR(LPCWSTR wstr)
- {
- if (wstr == NULL)
- return NULL;
-
- return _wcsdup(wstr);
- }
-
- LPWSTR AllocLPWSTR(LPCSTR str)
- {
- if (str == NULL)
- return NULL;
-
- size_t len = strlen(str);
- size_t retsize = mbstowcs(NULL, str, len);
- WCHAR *ret = (WCHAR *)malloc((retsize + 1) * sizeof(WCHAR));
- if (!ret)
- return NULL;
- mbstowcs(ret, str, len);
- ret[retsize] = L'\0';
- return ret;
- }
-
- LPSTR AllocLPSTR(LPCWSTR wstr)
- {
- if (wstr == NULL)
- return NULL;
-
- size_t len = wcslen(wstr);
- size_t retsize = WideCharToMultiByte(CP_ACP, 0, wstr, -1, NULL, 0, NULL, NULL);
- CHAR *ret = (CHAR *)malloc((retsize + 1) * sizeof(CHAR));
- if (!ret)
- return NULL;
- WideCharToMultiByte(CP_ACP, 0, wstr, -1, ret, retsize, NULL, NULL);
- ret[retsize] = '\0';
- return ret;
- }
-
- LPSTR AllocLPSTR(LPCSTR str)
- {
- if (str == NULL)
- return NULL;
-
- return _strdup(str);
- }
-
- LPTSTR AllocFileNameNoPath(LPTSTR path)
- {
- TCHAR fname[_MAX_FNAME];
- TCHAR ext[_MAX_EXT];
-
- if (path == NULL) return NULL;
-
- _tsplitpath(path, NULL, NULL, fname, ext);
-
- LPTSTR ret = (LPTSTR)malloc(sizeof(TCHAR) * (_tcslen(fname) + _tcslen(ext) + 1));
- if (ret != NULL)
- {
- _tcscpy(ret, fname);
- _tcscat(ret, ext);
- }
-
- return ret;
- }
-
- LPTSTR utilstr::Eject()
- {
- LPTSTR str = m_str;
- m_str = NULL;
- m_len = 0;
- return str;
- }
-
- void utilstr::Empty()
- {
- if (m_str != NULL)
- free(m_str);
- m_len = 0;
- }
-
- bool utilstr::IsEmpty() const
- {
- return !GetLength();
- }
-
- int utilstr::GetLength() const
- {
- if (m_str == NULL)
- return 0;
- if (!m_len)
- return 0;
-
- return _tcslen(m_str);
- }
-
- void utilstr::Format(LPCTSTR format, ...)
- {
- static TCHAR buf[2048];
- va_list args;
- va_start(args, format);
- #ifdef WIN95
- {
- char *psz = NULL;
- char szDfs[1024]={0};
- strcpy(szDfs,format); // make a local copy of format string
- while (psz = strstr(szDfs,"%p")) // find each %p
- *(psz+1) = 'x'; // replace each %p with %x
- _vsntprintf(buf, sizeof(buf)/sizeof(TCHAR), szDfs, args); // use the local format string
- }
- #else
- {
- _vsntprintf(buf, sizeof(buf)/sizeof(TCHAR), format, args);
- }
- #endif
- va_end(args);
- equal(buf);
- }
-
- void utilstr::equal(LPCTSTR str)
- {
- Empty();
- if (str == NULL)
- return;
- m_len = _tcslen(str);
- m_str = (LPTSTR)malloc(sizeof(TCHAR) * (m_len + 1));
- if (m_str != NULL)
- _tcscpy(m_str, str);
- else
- m_len = 0;
- }
-
- void utilstr::add(LPCTSTR str)
- {
- if (str == NULL)
- return;
- if (IsEmpty())
- {
- equal(str);
- return;
- }
- int len = _tcslen(str);
- int newlen = m_len + len;
- LPTSTR newstr = (LPTSTR)malloc(sizeof(TCHAR) * (newlen + 1));
- if (newstr == NULL)
- return;
- _tcscpy(newstr, m_str);
- _tcscat(newstr, str);
- Empty();
- m_str = newstr;
- m_len = newlen;
- }
-
- LPTSTR AllocFlagStr(DWORD value, const AFS_FLAG flag[], int flags)
- {
- utilstr ret; // return string
- DWORD allknownbits = 0; // check value to see if there are any bits
- // set for which we don't have a define
-
- // handle each flag
- bool bflagfound = false;
- for (int i = 0; i < flags; i++)
- {
- // set bit for this flag in allknownbits
- allknownbits |= flag[i].value;
-
- // if this bit is set in the passed value, or the value
- // is zero and we're on the zero flag,
- // add the define for this bit/flag to the return string
- if (value ? value & flag[i].value : !flag[i].value)
- {
- // adding binary or operators between flags
- if (bflagfound)
- ret += _T(" | ");
- ret += flag[i].name;
- bflagfound = true;
- }
- }
-
- // now see if there are any unknown bits in passed flag
- DWORD unknownbits = value & ~allknownbits;
- if (unknownbits)
- {
- // add hex number for unknown bits
- utilstr unk;
- unk.Format(_T("0x%08X"), unknownbits);
- if (bflagfound)
- ret += _T(" | ");
- ret += unk;
- }
-
- // if value is zero (and no flags for zero) we should just set the string to "0"
- if (!value && !bflagfound)
- ret = _T("0");
-
- // now the string should definitely not be empty, in any case
- assert(!ret.IsEmpty());
-
- // finally, add a comment that has hex number for entire value
- // (for debugging)
- utilstr temp;
- temp.Format(_T(" /* 0x%08X */"), value);
- ret += temp;
-
- // done
- return ret.Eject();
- }
-
- void PutLinePoint(HDC hDC, POINT p)
- {
- MoveToEx(hDC, p.x, p.y, NULL);
- LineTo(hDC, p.x + 1, p.y);
- }
-
- void PolyLineArrowShadow(HDC hDC, POINT *p, int i)
- {
- PolyLineArrow(hDC, p, i, TRUE);
- }
-
- void PolyLineArrow(HDC hDC, POINT *rgpt, int nPoints, BOOL bDoShadow)
- {
- int i;
-
- if (rgpt == NULL || nPoints < 1)
- return;
-
- if (nPoints > 1)
- for (i = 0; i < nPoints - 1; i++)
- {
- SPOINT a = rgpt[i], b = rgpt[i + 1];
-
- if (bDoShadow)
- {
- int rise = abs(b.y - a.y), run = abs(b.x - a.x);
- bool vert = rise > run;
- int ord = vert ? 1 : 0;
- int nord = vert ? 0 : 1;
-
- for (int o = -1; o <= 1; o += 2)
- {
- SPOINT c(a), d(b);
- c.a[nord] += o;
- d.a[nord] += o;
- MoveToEx(hDC, c.x, c.y, NULL);
- LineTo(hDC, d.x, d.y);
- }
-
- bool reverse = a.a[ord] > b.a[ord];
- SPOINT e(reverse ? b : a), f(reverse ? a : b);
- e.a[ord] -= 1;
- f.a[ord] += 1;
- PutLinePoint(hDC, e);
- PutLinePoint(hDC, f);
- }
- else
- {
- MoveToEx(hDC, a.x, a.y, NULL);
- LineTo(hDC, b.x, b.y);
- }
- }
-
- POINT z = rgpt[nPoints - 1];
-
- if (bDoShadow)
- {
- POINT pt[5] = {
- {z.x, z.y + 2},
- {z.x + 2, z.y},
- {z.x, z.y - 2},
- {z.x - 2, z.y}, };
- pt[4] = pt[0];
- Polyline(hDC, pt, 5);
- }
- else
- {
- MoveToEx(hDC, z.x - 1, z.y, NULL);
- LineTo(hDC, z.x + 2, z.y);
- MoveToEx(hDC, z.x, z.y - 1, NULL);
- LineTo(hDC, z.x, z.y + 2);
- }
- }
-
- BOOL bEq(BOOL a, BOOL b)
- {
- bool c = !a, d = !b;
- return (c == d) ? TRUE : FALSE;
- }
-
- void DrawArrow(HDC hDC, const RECT &rect, BOOL bVert, BOOL bUpLeft)
- {
- SRECT srect = rect;
- srect.right--;
- srect.bottom--;
- int ord = bVert ? 1 : 0;
- int nord = bVert ? 0 : 1;
- SPOINT p(!bUpLeft ? srect.lr : srect.ul), b(!bUpLeft ? srect.ul : srect.lr);
- b.a[ord] += bUpLeft ? -1 : 1;
- SPOINT t = p;
- t.a[nord] = (p.a[nord] + b.a[nord]) / 2;
- SPOINT u;
- u.a[ord] = b.a[ord];
- u.a[nord] = p.a[nord];
- POINT poly[] = { {t.x, t.y}, {u.x, u.y}, {b.x, b.y} };
- Polygon(hDC, poly, 3);
- }
-
- BOOL ScreenToClient(HWND hWnd, LPRECT rect)
- {
- if (rect == NULL)
- return FALSE;
-
- SRECT sr = *rect;
-
- if (ScreenToClient(hWnd, &sr.ul.p) &&
- ScreenToClient(hWnd, &sr.lr.p))
- {
- *rect = sr;
- return TRUE;
- }
-
- return FALSE;
- }
-
- BOOL ClientToScreen(HWND hWnd, LPRECT rect)
- {
- if (rect == NULL)
- return FALSE;
-
- SRECT sr = *rect;
-
- if (ClientToScreen(hWnd, &sr.ul.p) &&
- ClientToScreen(hWnd, &sr.lr.p))
- {
- *rect = sr;
- return TRUE;
- }
-
- return FALSE;
- }
-
- #define z ((L"\0")[0])
-
- int StrLen(LPCWSTR s)
- {
- if (s == NULL)
- return 0;
-
- return wcslen(s);
- }
-
- int StrLen(LPCSTR s)
- {
- if (s == NULL)
- return 0;
-
- return strlen(s);
- }
-
-